﻿using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Liphofra.Mvvm.ViewModels
{
    /// <summary>
    /// Extends the view model base class with typical data-oriented behavior like the definition of a model property and 
    /// for example an implementation of the <see cref="IChangeTracking"/> interface.
    /// </summary>
    /// <typeparam name="T">The type of the underlying view model.</typeparam>
    public abstract class DataViewModelBase<T> : ViewModelBase, IChangeTracking where T : class
    {
        /// <summary>
        /// Gets the underlying model this view model validates
        /// </summary>
        protected abstract T Model
        {
            get;
        }

        /// <summary>
        /// Called when a property has changed to update the change tracking and raise the corresponding <see cref="ViewModelBase.PropertyChanged" /> event.
        /// Must be called by derived classes to preserve correct notification and change tracking support.
        /// </summary>
        /// <param name="propertyName">The name of the property that has changed.</param>
        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            // set the changed flag
            IsChanged = true;

            base.OnPropertyChanged(propertyName);
        }

        #region IChangeTracking

        /// <summary>
        /// Resets the object's state to unchanged by accepting the modifications.
        /// </summary>
        public void AcceptChanges()
        {
            IsChanged = false;
        }

        /// <summary>
        /// Gets a value indicating whether the object's status has changed.
        /// </summary>
        /// <returns>true if the object's content has changed since the last call to <see cref="M:System.ComponentModel.IChangeTracking.AcceptChanges" />; otherwise, false. </returns>
        public bool IsChanged
        {
            get;
            private set;
        }

        #endregion
    }
}